//
// Created on 2024/4/29.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#include "WaterFlowNode.h"
#include "WaterFlowNode.h"
#include <arkui/native_type.h>

static constexpr std::array WATER_FLOW_NODE_EVENT_TYPES{NODE_SCROLL_EVENT_ON_SCROLL, NODE_SCROLL_EVENT_ON_SCROLL_START,
                                                  NODE_SCROLL_EVENT_ON_SCROLL_STOP,
                                                  NODE_SCROLL_EVENT_ON_SCROLL_FRAME_BEGIN};

WaterFlowNode::WaterFlowNode()
    : ArkUINode(NativeNodeApi::getInstance()->createNode(ArkUI_NodeType::ARKUI_NODE_WATER_FLOW)),
      m_waterFlowNodeDelegate(nullptr) {
    for (auto eventType : WATER_FLOW_NODE_EVENT_TYPES) {
        maybeThrow(NativeNodeApi::getInstance()->registerNodeEvent(m_nodeHandle, eventType, eventType, this));
    }
}

WaterFlowNode::~WaterFlowNode() {
    for (auto eventType : WATER_FLOW_NODE_EVENT_TYPES) {
        NativeNodeApi::getInstance()->unregisterNodeEvent(m_nodeHandle, eventType);
    }
}

WaterFlowNode &WaterFlowNode::setAdapter(ArkUI_NodeAdapterHandle adapter) {
    ArkUI_AttributeItem item{nullptr, 0, nullptr, adapter};
    maybeThrow(NativeNodeApi::getInstance()->setAttribute(m_nodeHandle, NODE_WATER_FLOW_NODE_ADAPTER, &item));
    return *this;
}

void WaterFlowNode::insertChild(ArkUINode &child, std::size_t index) {
    maybeThrow(NativeNodeApi::getInstance()->addChild(m_nodeHandle, child.getArkUINodeHandle()));
}

void WaterFlowNode::removeChild(ArkUINode &child) {
    maybeThrow(NativeNodeApi::getInstance()->removeChild(m_nodeHandle, child.getArkUINodeHandle()));
}

WaterFlowNode &WaterFlowNode::setLayoutDirection(int direction) {
//     auto waterFlowDirection = horizontal ? ArkUI_Axis::ARKUI_AXIS_HORIZONTAL : ArkUI_Axis::ARKUI_AXIS_VERTICAL;
//     ArkUI_NumberValue value[] = {{.i32 = waterFlowDirection}};
//     ArkUI_AttributeItem item = {value, sizeof(value) / sizeof(ArkUI_NumberValue)};
//     maybeThrow(NativeNodeApi::getInstance()->setAttribute(m_nodeHandle, NODE_LIST_DIRECTION, &item));
    
    return *this;
}

WaterFlowNode &WaterFlowNode::setCacheCount(int count) {
    ArkUI_NumberValue value[] = {{.i32 = count}};
    ArkUI_AttributeItem item = {value, sizeof(value) / sizeof(ArkUI_NumberValue)};
    maybeThrow(NativeNodeApi::getInstance()->setAttribute(m_nodeHandle, NODE_WATER_FLOW_CACHED_COUNT, &item));
    return *this;
}

WaterFlowNode &WaterFlowNode::setScrollBarDisplayMode(ArkUI_ScrollBarDisplayMode scrollBarDisplayMode) {
    ArkUI_NumberValue value[] = {{.i32 = scrollBarDisplayMode}};
    ArkUI_AttributeItem item = {value, sizeof(value) / sizeof(ArkUI_NumberValue)};
    maybeThrow(NativeNodeApi::getInstance()->setAttribute(m_nodeHandle, NODE_SCROLL_BAR_DISPLAY_MODE, &item));
    return *this;
}

WaterFlowNode &WaterFlowNode::setScrollBarColor(uint32_t scrollBarColor) {
    ArkUI_NumberValue value[] = {{.u32 = scrollBarColor}};
    ArkUI_AttributeItem item = {value, sizeof(value) / sizeof(ArkUI_NumberValue)};
    maybeThrow(NativeNodeApi::getInstance()->setAttribute(m_nodeHandle, NODE_SCROLL_BAR_COLOR, &item));
    return *this;
}

void WaterFlowNode::setNestedScrollMode(ArkUI_ScrollNestedMode scrollNestedMode) {
    std::array<ArkUI_NumberValue, 2> value{{{.i32 = scrollNestedMode}, {.i32 = scrollNestedMode}}};
    ArkUI_AttributeItem item = {value.data(), sizeof(value) / sizeof(ArkUI_NumberValue)};
    maybeThrow(NativeNodeApi::getInstance()->setAttribute(m_nodeHandle, NODE_SCROLL_NESTED_SCROLL, &item));
}

WaterFlowNode &WaterFlowNode::setEnableScrollInteraction(bool enableScrollInteraction) {
    ArkUI_NumberValue value[] = {{.i32 = enableScrollInteraction}};
    ArkUI_AttributeItem item = {value, sizeof(value) / sizeof(ArkUI_NumberValue)};
    maybeThrow(NativeNodeApi::getInstance()->setAttribute(m_nodeHandle, NODE_SCROLL_ENABLE_SCROLL_INTERACTION, &item));
    return *this;
}

void WaterFlowNode::scrollTo(float x, float y, bool animated) {
    ArkUI_AttributeItem item;
    ArkUI_NumberValue value[] = {{.f32 = x},
                                 {.f32 = y},
                                 {.i32 = animated ? 1000 : 0},
                                 {.i32 = ArkUI_AnimationCurve::ARKUI_CURVE_SMOOTH},
                                 {.i32 = 0}};
    item = {value, sizeof(value) / sizeof(ArkUI_NumberValue)};
    maybeThrow(NativeNodeApi::getInstance()->setAttribute(m_nodeHandle, NODE_SCROLL_OFFSET, &item));
}

void WaterFlowNode::setNodeScrollDelegate(WaterFlowNodeScrollDelegate *waterFlowNodeDelegate) {
    m_waterFlowNodeDelegate = waterFlowNodeDelegate;
}

void WaterFlowNode::onNodeEvent(ArkUI_NodeEventType eventType, EventArgs &eventArgs) {
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "onNodeEvent", "onNodeEvent Scroll");
    if (eventType == ArkUI_NodeEventType::NODE_SCROLL_EVENT_ON_SCROLL) {
        if (m_waterFlowNodeDelegate != nullptr) {
            m_waterFlowNodeDelegate->onScroll();
        }
    } else if (eventType == ArkUI_NodeEventType::NODE_SCROLL_EVENT_ON_SCROLL_START) {
        if (m_waterFlowNodeDelegate != nullptr) {
            m_waterFlowNodeDelegate->onScrollStart();
        }
    } else if (eventType == ArkUI_NodeEventType::NODE_SCROLL_EVENT_ON_SCROLL_STOP) {
        if (m_waterFlowNodeDelegate != nullptr) {
            m_waterFlowNodeDelegate->onScrollStop();
        }
    } else if (eventType == ArkUI_NodeEventType::NODE_SCROLL_EVENT_ON_SCROLL_FRAME_BEGIN) {
        if (m_waterFlowNodeDelegate != nullptr) {
            auto remainingOffset = m_waterFlowNodeDelegate->onScrollFrameBegin(eventArgs[0].f32, eventArgs[1].i32);
            eventArgs[0].f32 = remainingOffset;
        }
    }
}